《嵌入式系统 – 玩转ART-Pi开发板》第7章 环境监测系统(三)

《嵌入操作系统 – 玩转ART-Pi开发板》第7章 环境监测系统(一)

《嵌入操作系统 – 玩转ART-Pi开发板》第7章 环境监测系统(二)

7.4 数据上传到OneNET

7.4.1 OneNET简介

OneNET 平台是中国移动基于物联网产业打造的生态平台,具有高并发可用、多协议接入、丰富 API 支持、数据安全存储、快速应用孵化等特点,同时,OneNET 平台还提供全方位支撑,加速用户产品的开发速度。

OneNET平台是一个基于物联网产业特点打造的生态环境,可以适配各种网络环境和协议类型,现在支持的协议有LWM2M(NB-IOT)、EDP、MQTT、HTTP、MODBUS、JT\T808、TCP透传、RGMP等。用户可以根据不同的应用场景选择不同的接入协议。

OneNET 软件包是 RT-Thread 系统针对 OneNET 平台连接的适配,通过这个组件包可以让设备在 RT-Thread 上非常方便的连接 OneNet 平台,完成数据的发送、接收、设备的注册和控制等功能。
OneNET 软件包数据的上传和命令的接收是基于 MQTT 实现的,OneNET 的初始化其实就是 MQTT 客户端的初始化,初始化完成后,MQTT 客户端会自动连接 OneNET 平台。数据的上传其实就是往特定的 topic 发布消息。当服务器有命令或者响应需要下发时,会将消息推送给设备。

获取数据流、数据点,发布命令则是基于 HTTP Client 实现的,通过 POST 或 GET 将相应的请求发送给 OneNET 平台,OneNET 将对应的数据返回,这样,我们就能在网页上或者手机 APP 上看到设备上传的数据了。

下图是应用显示设备上传数据的流程图:

cItFmt.png

图23数据上传

下图是应用下发命令给设备的流程图

cItTN8.png

图24命令下发

7.4.2准备工作

在 OneNET 云上注册账号

设备接入 OneNET 云之前,需要在平台注册用户账号,OneNET 云平台地址:
https://open.iot.10086.cn

创建产品
账号注册登录成功后,点击开发者中心进入开发者中心界面;

cItb9g.png

图25创建产品

点击创建产品,输入产品基本参数,如下图所示:

cItq3Q.png

图26添加产品

产品创建成功之后,可以在开发者中心的公开协议产品中找到刚刚创建的产品,点击产品名,可以看到产品的基础信息(如产品ID,接入协议,创建时间,产品 APIkey 等,后面有用):

cINSEV.png

图27产品概述

接入设备
在开发者中心左侧设备管理中点击添加设备按钮添加设备。

cIN94U.png

图28添加设备

设备名称我们填入DHT11。鉴权信息是为了区分每一个不同的设备,如果创建了多个设备,要确保每个设备的鉴权信息都不一样,我们这里填入202104150903,填完之后点击接入设备。

cINFgJ.png

图29添加设备

添加 APIkey
接入设备之后,可以看到设备列表的界面多了一个设备,设备的右边有一些操作设备的按钮,点击查看详情按钮。

cINZHx.png

图30设备信息

此设备的相关信息就都显示出来了,比如:设备 ID、鉴权信息、设备 APIkey,这些信息需要记下,在ENV配置时会用到。

点击按钮添加 APIkey,APIKey 的名称一般和设备相关联,我们这里填入DHT11_APIKey,关联设备默认为我们刚刚创建的设备DHT11。

cIN8KA.png

图31添加APIkey

到此,云端的操作暂时就完成了。

7.4.3开启OneNET软件包

打开 RT-Thread Settings,开启 onenet 软件包,勾选onenet 软件包后,进入 onenet 软件包的配置菜单按下图所示配置,里面的信息依据自己的产品和设备的实际情况填写。

cINU58.png

图32配置OneNET

【配置说明】
Enable OneNET sample :开启 OneNET 示例代码
Enable support MQTT protocol :开启 MQTT 协议连接 OneNET 支持
Enable OneNET automatic register device :开启 OneNET 自动注册设备功能
产品ID :配置云端创建产品时获取的产品ID
主/生产 Apikey :配置云端创建产品时获取的产品APIKey
cINw8g.png
设备ID :配置云端创建设备时获取的设备ID
身份验证信息 :配置云端创建产品时 用户自定义的鉴权信息 (每个产品的每个设备唯一)
API密钥 :配置云端创建设备时获取的 APIkey
cIN02Q.png

7.4.4使用 OneNET

生成工程后,我们可以在工程的 onenet 目录下看到onenet_sample.c文件,该文件是 OneNET 软件包的示例展示,主要是展示用户如何使用 OneNET 软件包上传数据和接收命令。

在使用 OneNET 软件包之前必须要先调用onenet_mqtt_init这个命令进行初始化,初始化完成后设备会自动连接 OneNET 平台。

msh />onenet_mqtt_init
[D/onenet.mqtt] Enter mqtt_connect_callback!
[D/[mqtt] ] ipv4 address port: 6002
[D/[mqtt] ] HOST = '183.230.40.39'
[I/ONENET] RT-Thread OneNET package(V1.0.0) initialize success.
msh />[I/[mqtt] ] MQTT server connect success
[D/ onenet.mqtt] Enter mqtt_online_callback!

cINybq.png

7.4.4.1上传数据

初始化完成后,用户可以调用onenet_upload_cycle这个命令周期性的往云平台上传数据。输入这个命令后,设备会每隔 5s 向数据流 temperature 上传一个随机值。并将上传的数据打印到 shell 窗口。

msh />onenet_upload_cycle
[D/ onenet.sample] buffer : {"temperature":22}

cINgaV.png

我们打开 OneNET 平台,在设备列表界面选择刚添加的设备并进入数据流展示页面。

cINIM9.png

图33数据流

点击temperature数据流左边的小箭头显示数据流信息,我们就可以看到刚刚上传的数据了。
如果用户想往别的数据流发送信息,可以使用以下 API 往云平台上传数据。

onenet_mqtt_publish_digit onenet_mqtt_publish_string

命令格式如下所示:

onenet_mqtt_publish_digit 数据流名称 要上传的数据
onenet_mqtt_publish_string 数据流名称 要上传的字符串

输入命令后没有返回错误信息就表示上传成功。示例如下:

msh />onenet_mqtt_publish_digit test 1
msh />onenet_mqtt_publish_string test 1
msh />onenet_mqtt_publish_digit test 2
msh />onenet_mqtt_publish_string test 1

7.4.4.2接收数据

在初始化时,命令响应回调函数默认指向了空,想要接收命令,必须设置命令响应回调函数,在 shell 中输入命令onenet_set_cmd_rsp,就把示例文件里的命令响应回调函数挂载上了,这个响应函数在接收到命令后会把命令打印出来。

msh />onenet_set_cmd_rsp

我们点击设备列表界面的下发命令按钮。

cINTq1.png

图34下发命令

就可以在 shell 中看到云平台下发的命令了。

cINba6.png

7.4.4.3温湿度数据上传

以上是如何开启和简单使用OneNET,接下来需要将前面获取的温湿度进行上传,修改onenet_sample.c的代码:

#include <stdlib.h>
#include <onenet.h>
#include <wlan_mgnt.h>
#include "dht11_thread.h"

#define DBG_ENABLE
#define DBG_COLOR
#define DBG_SECTION_NAME    "onenet.sample"
#if ONENET_DEBUG
#define DBG_LEVEL           DBG_LOG
#else
#define DBG_LEVEL           DBG_INFO
#endif /* ONENET_DEBUG */

#include <rtdbg.h>

#ifdef FINSH_USING_MSH
#include <finsh.h>

extern rt_dht11 dht11;

static int onenetOk = -1;

/* upload random value to temperature*/
static void onenet_upload_entry(void *parameter)
{
    while (1)
    {
        if(onenetOk == 1)
        {
            //dht11
            //temperature
            if (onenet_mqtt_upload_digit("temperature", dht11.temp) < 0)
            {
                LOG_E("upload has an error, please check the network");
                break;
            }
            else
            {
                LOG_D("buffer : {\"temperature\":%d}", dht11.temp);
            }

            rt_thread_delay(rt_tick_from_millisecond(2 * 1000));

            //humidity
            if (onenet_mqtt_upload_digit("humidity", dht11.humi) < 0)
            {
                LOG_E("upload has an error, please check the network");
                break;
            }
            else
            {
                LOG_D("buffer : {\"humidity\":%d}", dht11.humi);
            }
        }
        rt_thread_delay(rt_tick_from_millisecond(5 * 1000));
    }
}

int onenet_upload_cycle(void)
{
    rt_thread_t tid;

    tid = rt_thread_create("onenet_send",
                           onenet_upload_entry,
                           RT_NULL,
                           2 * 1024,
                           RT_THREAD_PRIORITY_MAX / 3 - 1,
                           5);
    if (tid)
    {
        rt_thread_startup(tid);
    }

    return 0;
}

//MSH_CMD_EXPORT(onenet_upload_cycle, send data to OneNET cloud cycle);
INIT_APP_EXPORT(onenet_upload_cycle);

int onenet_publish_digit(int argc, char **argv)
{
    if (argc != 3)
    {
        LOG_E("onenet_publish [datastream_id]  [value]  - mqtt pulish digit data to OneNET.");
        return -1;
    }

    if (onenet_mqtt_upload_digit(argv[1], atoi(argv[2])) < 0)
    {
        LOG_E("upload digit data has an error!\n");
    }

    return 0;
}
MSH_CMD_EXPORT_ALIAS(onenet_publish_digit, onenet_mqtt_publish_digit, send digit data to onenet cloud);

int onenet_publish_string(int argc, char **argv)
{
    if (argc != 3)
    {
        LOG_E("onenet_publish [datastream_id]  [string]  - mqtt pulish string data to OneNET.");
        return -1;
    }

    if (onenet_mqtt_upload_string(argv[1], argv[2]) < 0)
    {
        LOG_E("upload string has an error!\n");
    }

    return 0;
}
MSH_CMD_EXPORT_ALIAS(onenet_publish_string, onenet_mqtt_publish_string, send string data to onenet cloud);

/* onenet mqtt command response callback function */
static void onenet_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
    char res_buf[] = { "cmd is received!\n" };

    LOG_D("recv data is %.*s\n", recv_size, recv_data);

    /* user have to malloc memory for response data */
    *resp_data = (uint8_t *) ONENET_MALLOC(strlen(res_buf));

    strncpy((char *)*resp_data, res_buf, strlen(res_buf));

    *resp_size = strlen(res_buf);
}

/* set the onenet mqtt command response callback function */
int onenet_set_cmd_rsp(int argc, char **argv)
{
    onenet_set_cmd_rsp_cb(onenet_cmd_rsp_cb);
    return 0;
}
MSH_CMD_EXPORT(onenet_set_cmd_rsp, set cmd response function);

/* onenet init*/
static void onenet_init_entry(void *parameter)
{
    int result = -1;
    while(1)
    {
        if (rt_wlan_is_connected())
        {
            result = onenet_mqtt_init();
            if(result == 0)
            {
                onenetOk = 1;
                break;
            }
        }
        rt_thread_delay(5000);
    }
}

int onenet_init(void)
{
    rt_thread_t tid;

    tid = rt_thread_create("onenet_init",
                           onenet_init_entry,
                           RT_NULL,
                           2 * 1024,
                           RT_THREAD_PRIORITY_MAX / 2 - 1,
                           5);
    if (tid)
    {
        rt_thread_startup(tid);
    }

    return 0;
}

INIT_APP_EXPORT(onenet_init);

#endif /* FINSH_USING_MSH */

主要添加了自动初始化OneNET,修改onenet_upload_entry()的内容,添加DHT11温湿度获取的功能。

值得注意的是,联网后才进行OneNET初始化,还可以优化的地方就是配置OneNET成自动化,在初始化中加入网络是否连接的判断,这样就不可不使用终端来打开OneNET,当然啦,上传数据也是如此。另外在上传每条记录后,需要有一定的延时,不然后面的信息上传不成功。

打开设备后,现象如下:

cINOPO.png

当然啦,最后调试成功后关闭打印信息,云端则可看到上传的数据。

cINXGD.png

图35数记录

7.4.5 OneNET创建应用

点击左侧 【应用管理】 然后点击 【创建应用】。

cINjRe.png

图36创建应用

然后输入应用名称并点击 【创建】。

cIUpqI.png

图37

在弹出的窗口中编辑应用,可以拖动左侧元件库中的元件到中间的显示区域

cIUCZt.png

图38

点击要设置的元件可以在右侧的 属性和样式 窗口改变元件的属性。

cIUPdP.png

图39

最后的效果如下所示:

cIUERg.png

图40云端应用

7.5 总结

最后,我们来总结下这个项目,整个过程很简单,数据采集,联网,数据上传,当然数据采集和联网可以并行,当联网成功后就可以进行数据传输。

cIUVzQ.png

笔者简单起见,这里就在网关上接个传感器来获得环境信息,如果读者朋友有兴趣可以单独将环境监测的部分提取出来,使用单独的板子获得更多的环境信息,或者使用ZigBee/BLE等组网来监测更多的信息和区域。

网关部分,使用ART-Pi一般能满足要求,这里只是简单的传输数据,如果有其他需求,可考虑换用其他网关。

本文使用的云服务是OneNET,当然也可使用其他云服务,阿里云也不错,资料也比较多。

好了,这个项目就到这里了,有兴趣的,一起来玩玩吧。


资源获取方法

1.长按下面二维码,关注公众号[嵌入式实验楼]
2.在公众号回复关键词[Art-Pi]获取资料提取码

嵌入式实验楼

Related posts

Leave a Comment